<template>
  <view class="container">
    <button @click="chooseImages">选择图片并拼接</button>
    <image v-if="resultImage" :src="resultImage" mode="widthFix" class="result-image"></image>
    <button v-if="resultImage" @click="uploadImage">上传拼接结果</button>
    <progress v-if="uploading" :percent="uploadProgress" show-info></progress>
  </view>
</template>

<script>
export default {
  data() {
    return {
      images: [],
      resultImage: "",
      canvasWidth: 0,
      canvasHeight: 0,
      uploading: false,
      uploadProgress: 0
    };
  },
  methods: {
    // 选择多张图片
    async chooseImages() {
      try {
        const res = await uni.chooseImage({
          count: 9,
          sizeType: ['compressed'],
          sourceType: ['album']
        });

        this.images = res.tempFilePaths;
        await this.combineImages();
      } catch (err) {
        uni.showToast({ title: '选择图片失败', icon: 'none' });
      }
    },

    // 拼接图片
    async combineImages() {
      if (this.images.length < 2) {
        uni.showToast({ title: '请至少选择2张图片', icon: 'none' });
        return;
      }

      uni.showLoading({ title: '拼接中...', mask: true });

      try {
        // 获取所有图片信息
        const imageInfos = await Promise.all(
          this.images.map(path =>
            new Promise((resolve, reject) => {
              uni.getImageInfo({
                src: path,
                success: resolve,
                fail: reject
              });
            })
          )
        );

        // 计算画布尺寸
        this.canvasWidth = Math.max(...imageInfos.map(info => info.width));
        this.canvasHeight = imageInfos.reduce((sum, info) => {
          const ratio = info.width / this.canvasWidth;
          return sum + info.height / ratio;
        }, 0);

        // 创建离屏画布
        const canvas = uni.createOffscreenCanvas({
          type: '2d',
          width: this.canvasWidth,
          height: this.canvasHeight
        });
        const ctx = canvas.getContext('2d');

        // 绘制所有图片
        let currentY = 0;
        for (const info of imageInfos) {
          const ratio = info.width / this.canvasWidth;
          const drawHeight = info.height / ratio;

          await new Promise((resolve) => {
            const img = canvas.createImage();
            img.onload = () => {
              ctx.drawImage(img, 0, currentY, this.canvasWidth, drawHeight);
              currentY += drawHeight;
              resolve();
            };
            img.src = info.path;
          });
        }

        // 生成结果图片
        const res = await uni.canvasToTempFilePath({
          canvas,
          fileType: 'jpg',
          quality: 0.8
        });

        this.resultImage = res.tempFilePath;
        uni.hideLoading();
      } catch (err) {
        uni.hideLoading();
        uni.showToast({ title: '图片拼接失败', icon: 'none' });
      }
    },

    // 上传图片
    async uploadImage() {
      if (!this.resultImage) return;

      this.uploading = true;
      this.uploadProgress = 0;

      try {
        const res = await uni.uploadFile({
          url: '/api/upload',
          filePath: this.resultImage,
          name: 'image',
          header: {
            'Authorization': 'Bearer your-token-here' // 替换为实际token
          },
          formData: {
            type: 'combined_image'
          },
          success: (uploadRes) => {
            const data = JSON.parse(uploadRes.data);
            if (data.code === 200) {
              uni.showToast({ title: '上传成功' });
            } else {
              uni.showToast({ title: `上传失败: ${data.message}`, icon: 'none' });
            }
          },
          fail: (err) => {
            uni.showToast({ title: '上传失败', icon: 'none' });
          },
          complete: () => {
            this.uploading = false;
          }
        });

        // 监听上传进度
        res.onProgressUpdate = (res) => {
          this.uploadProgress = res.progress;
        };
      } catch (err) {
        this.uploading = false;
        uni.showToast({ title: '上传失败', icon: 'none' });
      }
    }
  }
};
</script>

<style>
.container {
  padding: 20rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}

button {
  width: 80%;
  margin: 20rpx 0;
  background-color: #007AFF;
  color: white;
}

.result-image {
  width: 100%;
  margin: 20rpx 0;
  border: 1rpx solid #eee;
}

progress {
  width: 80%;
  margin-top: 20rpx;
}
</style>
